import java.io.*;
import java.net.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import javax.swing.JOptionPane;

public class Server
{
	public static ArrayList<Email> serverEmail = new ArrayList<Email>();
	public static int index = 0;
	static Connection connection;
	static Statement statement;

	public static void main(String[] args) throws IOException, SQLException
	{
		ServerSocket serverSocket = null;
		final int PORT = 1234;
		Socket client;
		ClientHandler handler;

		String messages[][];

		try
		{
			serverSocket = new ServerSocket(PORT);
		}
		catch (IOException ioEx)
		{
			System.out.println("\nUnable to set up port!");
			System.exit(1);
		}

		
		//////////////////////////////////////////////////////////DATABASE STUFF////////////////////
		String fileName = "C:/Users/Jack/workspace/NSD Phase 2/emailDatabase.mdb";
		String dbString ="jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=" + fileName + ";DriverID=22;READONLY=false}"; //Change back to *mdb for 32bit access

		//Connection connection = null;
        //Statement statement = null;
    	//ResultSet results = null;
    	
    	try
		{
			Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
			connection = DriverManager.getConnection(dbString,"","");
			System.out.println("Server Connected To Database");
		}
		catch(ClassNotFoundException cnfEx)
		{
			JOptionPane.showMessageDialog(null,"* Unable to load driver! *");
			System.exit(1);
		}
		catch(SQLException sqlEx)
		{
			JOptionPane.showMessageDialog(null,"* Cannot connect to database! *");
			System.exit(1);
		}
    	////////////////////////////////////////////////////////////////////////////////////////////////
		
		System.out.println("\nServer running...\n");
		retrieveFromDB();
		do
		{
			client = serverSocket.accept();
			// Wait for client.
			System.out.println("\nNew client accepted.\n");

			handler = new ClientHandler(client);
			handler.start();

		} while (true);
	}

	public static void retrieveFromDB() throws SQLException
	{
		ResultSet results = null;
		//int numberOfMails = 0;
		Statement statement;
		
			statement = connection.createStatement();
			results = statement.executeQuery( "SELECT * FROM emails");
			

			while (results.next())
			{
				Email dbEmails = new Email(results.getString("emailRecipient"),results.getString("emailSender"),results.getString("emailMessage"),results.getString("emailCommand"),results.getString("emailFileName"),null, results.getString("emailFileLocation"));  //command);
		
				if (dbEmails.getFileLocation() != "none")
				{
					File newFile = new File(dbEmails.getFileLocation());
					dbEmails.mailFile = newFile;
				}
				
				serverEmail.add(dbEmails);
			
			}
	}
	
	public static void storeMessages(Email email)
	{
		
		if (email.getFileLocation() == "none") // If there is no attachment
		{
			email.setIndex(index);
			//serverEmail.add(email);
			System.out.println("<--------NEW EMAIL-------->");
			System.out.println("ID :" + email.getIndex());
			System.out.println("TO :" + email.getRecipient());
			System.out.println("MESSAGE : " + email.getMessage());
			System.out.println("FROM : " + email.getSender());
			System.out.println("<-------END OF EMAIL------>");
			
			/////////////INSERT INTO DATABASE///////////////
			String insertDB =   "INSERT INTO emails (emailRecipient, emailMessage, emailSender,emailCommand,emailFileName,emailFileLocation)" +
					" VALUES ('" + email.getRecipient() +
								"','" + email.getMessage() + "','" + email.getSender() + "','" + email.getCommand() +
								"','none','none')";
			
			Statement statement;
			try {
				statement = connection.createStatement();
				statement.executeUpdate(insertDB);
				System.out.println("<----EMAIL STORED IN DB------>");
			} catch (SQLException e) {
				e.printStackTrace();
			}
			////////////////////////////////////////////////
			serverEmail.add(email); // Updates the array whilst the program is running
			index++;
		}
		
		else // if there is an attachment
		{
			email.setIndex(index);
			//serverEmail.add(email);
			System.out.println("<--------NEW EMAIL-------->");
			System.out.println("ID :" + email.getIndex());
			System.out.println("TO :" + email.getRecipient());
			System.out.println("MESSAGE : " + email.getMessage());
			System.out.println("FROM : " + email.getSender());
			System.out.println("<-------END OF EMAIL------>");
			
			/////////////INSERT INTO DATABASE///////////////
			String insertDB =  "INSERT INTO emails (emailRecipient, emailMessage, emailSender,emailCommand,emailFileName,emailFileLocation)" +
								" VALUES ('" + email.getRecipient() +
								"','" + email.getMessage() + "','" + email.getSender() + "','" + email.getCommand() +
								"','" + email.getFileName() + "','" + email.getFileLocation()
								+ "')";
			
			Statement statement;
			try {
				statement = connection.createStatement();
				statement.executeUpdate(insertDB);
				System.out.println("<----EMAIL STORED IN DB------>");
			} catch (SQLException e) {
				e.printStackTrace();
			}
			////////////////////////////////////////////////
			serverEmail.add(email); // updates the array whilst the program is running
			index++;
		}

		
		
		/*
		email.setIndex(index);
		serverEmail.add(email);
		System.out.println("<--------NEW EMAIL-------->");
		System.out.println("ID :" + email.getIndex());
		System.out.println("TO :" + email.getRecipient());
		System.out.println("MESSAGE : " + email.getMessage());
		System.out.println("FROM : " + email.getSender());
		System.out.println("<-------END OF EMAIL------>");
		index++; */
	}
	
	public static void storeMessageAttachment(Email email, String userName) throws IOException
	{
        File file = email.getFile();
        String newFileLocation = "Attachments/"+ userName + "_" + file.getName();
        
        File newFile = new File(newFileLocation);
        FileInputStream finStream = new FileInputStream(file);
        
        long fileLength =  (file.length());
        
        int intFileLength = (int)fileLength;
        byte[] byteArray = new byte[intFileLength];
        
        finStream.read(byteArray);
        finStream.close();
        
        FileOutputStream foutStream = new FileOutputStream(newFile);
        
        foutStream.write(byteArray);
        foutStream.flush();
        
        email.setFileLocation(newFileLocation); // sets location of the file that was just stored
        
        
        Server.storeMessages(email); // stores all information in the object array
        
        System.out.println("ATTACHMENT STORED AT : " + email.getFileLocation()); // shows attachment path
	}
	
	public static void deleteMessages(String deleteMessage)
	{
		  int index = Integer.parseInt(deleteMessage);
		  System.out.println("DELETING MAIL :" + index);

				serverEmail.remove(index);
		index--;		
	}

}

class ClientHandler extends Thread
{

	private ObjectOutputStream objOutput;
	private ObjectInputStream objInput;
	private Socket client;
	private Scanner input;
	private PrintWriter output;

	public ClientHandler(Socket socket) throws IOException
	{
		client = socket;
		objOutput = new ObjectOutputStream(socket.getOutputStream());
		objInput = new ObjectInputStream(socket.getInputStream());
		input = new Scanner(client.getInputStream());
		output = new PrintWriter(client.getOutputStream(), true);

	}

	public void run()
	{
		Email email = null;

		do // do this while the command is not quit
		{
			String userName;

			try
			{
				email = (Email) objInput.readObject();
				userName = email.getSender();

				if (email.getCommand().equals("login")) // if the login command is received
				{
					System.out.println(userName + " has logged on.");
				}

				if (email.getCommand().equals("newMessage")) // if someone has sent a new message
				{
					Server.storeMessages(email);
				}
				
				if (email.getCommand().equals("newMessageAttachment")) // if someone has sent a message with an attachment
				{
					
					Server.storeMessageAttachment(email, userName);
					

				}

				if (email.getCommand().equals("readMailbox"))
				{
					try
					{
						int numberOfMails = 0;

						for (int i = 0; i < Server.serverEmail.size(); i++)
						{
							Email sendingMailbox = Server.serverEmail.get(i);
							String receiver = sendingMailbox.getRecipient();

							if (receiver.equals(userName))
							{
								numberOfMails++;
								objOutput.writeObject(sendingMailbox);
								objOutput.flush();
							}

						}

						System.out.println("Number of mails for"+ userName + " : "+ numberOfMails);

						if (numberOfMails == 0)
						{
							Email emptyMailbox = new Email(userName, "", "", "NOMAIL", null, null, null);
							objOutput.writeObject(emptyMailbox);
							objOutput.flush();
						}

						Email stopMailbox = new Email("", "","", "STOP", null, null, null);
						objOutput.writeObject(stopMailbox);
						objOutput.flush();

					}

					catch (IOException e)
					{
						JOptionPane.showMessageDialog(null,"Unable to send object");
					}
				}
				if (email.getCommand().equals("DELETE"))
				{
					String mailToDelete = email.getMessage();
					System.out.println(mailToDelete + " : ID In the Array");
					Server.deleteMessages(mailToDelete);
					
				}
				
			}
			catch (IOException e1)
			{

			}
			catch (ClassNotFoundException e1)
			{

			}

		} while (!email.getCommand().equals("QUIT"));// !received.equals("QUIT"));

		try
		{
			System.out.println("Closing down connection...");
			// output.println("GOODBYE");
			client.close();
		}
		catch (IOException ioEx)
		{
			System.out.println("* Disconnection problem! *");
		}
	}

}
